package fr.univ.projet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class Jeu
{
    // Type de jeu
    private String typeJeu = "Jeu";
    
    // numéro unique identifiant le jeu
    private int numero;
    
    // Règle du jeu pour les numéros simples
    private int numeroMin = 1;
    private int numeroMax = 4;
    private int nbreNumero = 4;
    
    // Règle du jeu pour les numéros chances
    private int numeroChanceMin = 1;
    private int numeroChanceMax = 10;
    private int nbreNumeroChance = 0;

    // Liste des numéros gagnants
    private List<Numero> numerosGagnants;
    
    // Map permettant de rassembler l'ensemble des résultats du jeu ( numéros gagnants simples et numéro gagnant chance )
    private Map<String, Object> mapResult;
    
    /**
     * Clé permettant de retrouver la liste des numéros gagnants dans la map
     * 
     */
    public static final String CODE_MAP_NUMS_GAGNANTS = "Numeros";
    
    /**
     * Clé permettant de retrouver le numéro chance gagnant dans la map
     */ 
    public static final String CODE_MAP_NUM_CHANCE = "Chance";
    
    /**
     * Initialisation d'un jeu
     * 
     * @param pNum numéro unique du jeu
     */
    public Jeu(int pNum)
    {
        this.numerosGagnants = new ArrayList<Numero>();
        this.mapResult = new HashMap<String, Object>();
        this.numero = pNum;
    }

    /**
     * Test si le numéro est déjà présent dnas la liste des numéros gagnants
     * 
     * @param pNumero numéro à tester
     * 
     * @return vrai si le numéro est trouvé dans la liste et faux si c'est pas le cas
     */
    protected boolean estDejaTirer(int pNumero)
    {
        boolean trouve = false;
        Numero num = new Numero(pNumero);
        
        if ( getNumerosGagnants().contains(num))
            trouve = true;
        
        return trouve;
    }
    
    /**
     * Test si le tirage du jeu a été fait
     * 
     * @return vrai si le tirage est fait et faux sinon
     */
    public boolean isTirageFait()
    {
        boolean tirageFait = false;
        
        if ( getNumerosGagnants().size() > 0 )
        {
            tirageFait = true;
        }
        
        return tirageFait;
    }
    
    /**
     * Réalise le tirage au sort du jeu en fonction des règles propres au jeu
     */
    public abstract void tirage();
    
    /**
     *  Calcule les gains d'une grille du jeu en fonction des règles propre au jeu
     * 
     * @param pGrille Grille dont on désire connaitre les gains
     * 
     * @return  les gains de la grille.
     */
    public abstract float calculGainsGrille(Grille pGrille);

    /**
     * 
     * @return la valeur de la borne inférieur de la grille des numéros "simples"
     */
    public int getNumeroMin()
    {
        return numeroMin;
    }

    /**
     * 
     * @return la valeur de la borne supérieure de la grille des numéros "simples"
     */
    public int getNumeroMax()
    {
        return numeroMax;
    }
    
    

    /**
     * 
     * @return le nombre de numéros "simples" à jouer par grille
     */
    public int getNbreNumero()
    {
        return nbreNumero;
    }

    /**
     * 
     * @return la valeur de la borne inférieure des numéros chances
     */
    public int getNumeroChanceMin()
    {
        return numeroChanceMin;
    }

    /**
     * 
     * @return la valeur de la borne supérieur des numéros chances
     */
    public int getNumeroChanceMax()
    {
        return numeroChanceMax;
    }

    /**
     * 
     * @return le nombre de numéros chances à jouer par grille
     */
    public int getNbreNumeroChance()
    {
        return nbreNumeroChance;
    }
    
    /**
     * 
     * @return retourne la map pouvant contenir les numéros simples gagnants et numero chance gagnant
     */
    public Map<String, Object> getMapResult()
    {
        return mapResult;
    }

    /**
     * 
     * @param pCode code la grille
     * @param pJoueur joueur jouant la grille
     * 
     * @return une grille 
     */
    public Grille faireGrille(int pCode, Joueur pJoueur) 
    {
        return new Grille(pCode,this,pJoueur);
    }

    /**
     * 
     * @param pNumero numéro identifiant le jeu
     */
    public void setNumero(int pNumero) {
        this.numero = pNumero;
    }
    /**
     * 
     * @return le type de jeu
     */
    public String getTypeJeu() {
        return typeJeu;
    }

    /**
     * 
     * @param pNumeroMin valeur de la borne inférieur des numéros simples
     */
    protected void setNumeroMin(int pNumeroMin)
    {
        this.numeroMin = pNumeroMin;
    }

    /**
     * 
     * @param pNumeroMax valeur de la borne supérieur des numéros simples
     */
    protected void setNumeroMax(int pNumeroMax)
    {
        this.numeroMax = pNumeroMax;
    }

    /**
     * 
     * @param pNbreNumero nombre de numéro simple par grille
     */
    protected void setNbreNumero(int pNbreNumero)
    {
        this.nbreNumero = pNbreNumero;
    }

    /**
     * 
     * @param pNumeroChanceMin valeur de la borne inférieure des numéros chance
     */
    protected void setNumeroChanceMin(int pNumeroChanceMin)
    {
        this.numeroChanceMin = pNumeroChanceMin;
    }

    /**
     * 
     * @param pNumeroChanceMax valeur de la borne supérieure des numéros chance
     */
    protected void setNumeroChanceMax(int pNumeroChanceMax)
    {
        this.numeroChanceMax = pNumeroChanceMax;
    }

    /**
     * 
     * @param pNbreNumeroChance nombre de numéros chanc par grille
     */
    protected void setNbreNumeroChance(int pNbreNumeroChance)
    {
        this.nbreNumeroChance = pNbreNumeroChance;
    }

    /**
     * 
     * @return la liste des numéros gagnats
     */
    protected List<Numero> getNumerosGagnants()
    {
        return numerosGagnants;
    }

    /**
     * 
     * @param pTypeJeu le type de jeu
     */
    protected void setTypeJeu(String pTypeJeu) 
    {
        this.typeJeu = pTypeJeu;
    }
    
    @Override
    public boolean equals(Object pObj) {
        if (pObj == null) {
            return false;
        }
        if (getClass() != pObj.getClass()) {
            return false;
        }
        final Jeu other = (Jeu) pObj;
        if (this.numero != other.numero) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 41 * hash + this.numero;
        return hash;
    }

    @Override
    public String toString() 
    {
        if ( isTirageFait() )
        {
            if ( nbreNumeroChance == 0 )
                return typeJeu + " " + numero + " " + numerosGagnants ;
            else
            {
                Numero num = (Numero) mapResult.get(CODE_MAP_NUM_CHANCE);
                return typeJeu + " " + numero + " " + numerosGagnants + "/C:" + num.getValeur();
            }
        }
        else
            return typeJeu + " " + numero;
    }
    
}
